// Copyright (C) 2006 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


// The http_interact.cpp file contains low-level functions for performing
// HTTP requests using libcurl.  Users of this client library should not
// call these routines directly, but rely instead on the functionality in
// the rest of the client library.


#include <curl/curl.h>
#include "http_interact.h"

static const char hexAlphabet[] = "0123456789ABCDEF";

string UrlEncode(const string &s) {
  string result;

  for (unsigned i = 0; i < s.length(); ++i) {
    if (isalnum(s[i])) {
      result += s[i];
    } else {
      result += "%";
      result += hexAlphabet[static_cast<unsigned char>(s[i]) / 16];
      result += hexAlphabet[static_cast<unsigned char>(s[i]) % 16];
    }
  }

  return result;
}

// Called by libcurl as soon as there is data received
// from the HTTP connection.
static size_t writeCallback(void *data,
                            size_t blockSize,
                            size_t numBlocks,
                            void *userPtr) {
  string *userString = static_cast<string *>(userPtr);
  *userString += reinterpret_cast<char *>(data);

  return blockSize*numBlocks;
}

pair<bool, string> ExecutePost(const string &postUrl,
                               const string &postDocument) {
  CURL *curl = curl_easy_init();
  CURLcode res;
  string httpContent;

  if (curl) {
    curl_easy_setopt(curl, CURLOPT_URL, postUrl.c_str());
    curl_easy_setopt(curl, CURLOPT_POST, true);
    curl_easy_setopt(curl, CURLOPT_FAILONERROR, true);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postDocument.c_str());
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, true);

    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &httpContent);

    res = curl_easy_perform(curl);
    curl_easy_cleanup(curl);

    if (res == CURLE_OK) {
      return make_pair(true, httpContent);
    } else {
      return make_pair(false, "Error: HTTP transfer failed.");
    }
  } else {
    return make_pair(false, "Error: Could not initialize cURL handle.");
  }
}
